import cv2  # 我只用它来做图像读写和绘图，没调用它的其它函数哦
import numpy as np  # 进行数值计算


# padding 函数
def padding(img, K_size=3):
    # img 为需要处理图像
    # K_size 为滤波器也就是卷积核的尺寸，这里我默认设为3*3，基本上都是奇数

    # 获取图片尺寸
    H, W, C = img.shape

    pad = K_size // 2  # 需要在图像边缘填充的0行列数，
    # 之所以我要这样设置，是为了处理图像边缘时，滤波器中心与边缘对齐

    # 先填充行
    rows = np.zeros((pad, W, C), dtype=np.uint8)
    # 再填充列
    cols = np.zeros((H + 2 * pad, pad, C), dtype=np.uint8)
    # 进行拼接
    img = np.vstack((rows, img, rows))  # 上下拼接
    img = np.hstack((cols, img, cols))  # 左右拼接

    return img


# Prewitt 滤波函数
def laplacian(img, K_size=3):
    # 获取图像尺寸
    H, W, C = img.shape

    # 进行padding
    pad = K_size // 2
    out = padding(img, K_size=3)

    # 滤波器系数
    K = np.array([[0., 1., 0.], [1., -4., 1.], [0., 1., 0.]])

    # 进行滤波
    tem = out.copy()

    for h in range(H):
        for w in range(W):
            for c in range(C):
                out[pad + h, pad + w, c] = np.sum(K * tem[h:h + K_size, w:w + K_size, c], dtype=np.float)

    out = np.clip(out, 0, 255)

    out = out[pad:pad + H, pad:pad + W].astype(np.uint8)

    return out


# 这里需要把图像先灰度化
# 直接用之前的灰度化代码
# 灰度化函数
def BGR2GRAY(img):
    # 获取图片尺寸
    H, W, C = img.shape

    # 灰度化
    out = np.ones((H, W, 3))
    for i in range(H):
        for j in range(W):
            out[i, j, :] = 0.299 * img[i, j, 0] + 0.578 * img[i, j, 1] + 0.114 * img[i, j, 2]

    out = out.astype(np.uint8)

    return out




file_in = './lena.png'
file_out = './lena_laplacian.png'
img = cv2.imread(file_in)

# 调用函数进行灰度化
img = BGR2GRAY(img)
# 调用函数进行sobel滤波
out = laplacian(img)

# 保存图片
cv2.imwrite(file_out, out)
cv2.imshow("result", out)

cv2.waitKey(0)
cv2.destroyAllWindows()
